﻿namespace TestByWire.Test.AttributeHandlers.UseStubLateBound
{
    #region Usings
    using System;

    using Microsoft.Practices.Unity;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Rhino.Mocks;
    using TestByWire.AttributeHandlers;
    #endregion

    [TestClass]
    public class UseStubLateBoundAttributeTest
    {
        private UseStubLateBoundAttribute _target;
        private IBuildContext _buildContext;

        [TestInitialize]
        public void Init()
        {
            _buildContext = MockRepository.GenerateStub<IBuildContext>();
            _target = new UseStubLateBoundAttribute(typeof(IMyClass), "_foo");
        }

        [TestMethod]
        public void Inheritance()
        {
            Assert.IsInstanceOfType(_target, typeof(IContainerInteraction));
        }

        [TestMethod]
        public void Execute_MustThrow_WhenBuildContextIsNull()
        {
            var exception = AssertEx.Throws<ArgumentNullException>(() => _target.Execute(null));

            Assert.AreEqual("buildContext", exception.ParamName);
        }

        [TestMethod]
        public void Execute_MustOptOut_WhenBuildContextTestTargetIsNull()
        {
            _target.Execute(_buildContext);

            _buildContext.AssertWasNotCalled(t => { var ignore = t.Container; });
        }

        [TestMethod]
        public void Execute_MustThrow_WhenBuildContextContainerIsNull()
        {
            _buildContext.Stub(c => c.TestTarget).Return(_target);

            var exception = AssertEx.Throws<ArgumentException>(() => _target.Execute(_buildContext));

            Assert.IsTrue(exception.Message.StartsWith("Container property is not set"));
        }

        [TestMethod]
        public void Execute_MustThrow_WhenFieldNameIsWrong()
        {
            _target = new UseStubLateBoundAttribute(typeof(IMyClass), "no_such_field");
			_buildContext.Stub(c => c.TestTarget).Return(new LateBoundClass());
			_buildContext.Stub(c => c.Container).Return(new UnityContainer());

            var exception = AssertEx.Throws<InvalidOperationException>(() => _target.Execute(_buildContext));

			Assert.IsTrue(exception.Message.StartsWith("Field: no_such_field, does not exist on Test Target:"));
        }

		//[TestMethod]
		public void Execute_MustCreateInstanceOfStubType_WhenStubTypeIsNotSet()
		{
			var container = MockRepository.GenerateStub<IUnityContainer>();

			_buildContext.Stub(c => c.TestTarget).Return(new LateBoundClass());
			_buildContext.Stub(c => c.Container).Return(container);

			_target.Execute(_buildContext);

			Assert.Fail();
		}
    }

    public class LateBoundClass
    {
#pragma warning disable 169
        private IMyClass _foo;
#pragma warning restore 169
    }
}
